name: Image CI Build

# Any change in triggers needs to be reflected in the concurrency group.
on:
  pull_request_target:
    types:
      - opened
      - synchronize
      - reopened
  push:
    branches:
      - main
      - ft/main/**

  # If the cache was cleaned we should re-build the cache with the latest commit
  workflow_run:
    workflows:
     - "Image CI Cache Cleaner"
    branches:
     - main
     - ft/main/**
    types:
     - completed

permissions:
  # To be able to access the repository with `actions/checkout`
  contents: read
  # Required to generate OIDC tokens for `sigstore/cosign-installer` authentication
  id-token: write

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.event.after }}
  cancel-in-progress: true

jobs:
  build-and-push-prs:
    timeout-minutes: 45
    name: Build and Push Images
    runs-on: ubuntu-22.04
    strategy:
      matrix:
        include:
          - name: cilium
            dockerfile: ./images/cilium/Dockerfile

          - name: operator-aws
            dockerfile: ./images/operator/Dockerfile

          - name: operator-azure
            dockerfile: ./images/operator/Dockerfile

          - name: operator-alibabacloud
            dockerfile: ./images/operator/Dockerfile

          - name: operator-generic
            dockerfile: ./images/operator/Dockerfile

          - name: hubble-relay
            dockerfile: ./images/hubble-relay/Dockerfile

          - name: clustermesh-apiserver
            dockerfile: ./images/clustermesh-apiserver/Dockerfile

          - name: docker-plugin
            dockerfile: ./images/cilium-docker-plugin/Dockerfile

    steps:
      - name: Checkout default branch (trusted)
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
        with:
          ref: ${{ github.event.repository.default_branch }}
          persist-credentials: false

      - name: Set Environment Variables
        uses: ./.github/actions/set-env-variables

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0

      - name: Login to quay.io for CI
        uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
        with:
          registry: quay.io
          username: ${{ secrets.QUAY_USERNAME_CI }}
          password: ${{ secrets.QUAY_PASSWORD_CI }}

      - name: Getting image tag
        id: tag
        run: |
          if [ "${{ github.event.pull_request.head.sha }}" != "" ]; then
            echo tag=${{ github.event.pull_request.head.sha }} >> $GITHUB_OUTPUT
          else
            echo tag=${{ github.sha }} >> $GITHUB_OUTPUT
          fi
          if [ "${{ github.ref_name }}" == "${{ github.event.repository.default_branch }}" ]; then
            echo floating_tag=latest >> $GITHUB_OUTPUT
          else
            echo floating_tag=${{ github.ref_name }} >> $GITHUB_OUTPUT
          fi

      # Warning: since this is a privileged workflow, subsequent workflow job
      # steps must take care not to execute untrusted code.
      - name: Checkout pull request branch (NOT TRUSTED)
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
        with:
          persist-credentials: false
          ref: ${{ steps.tag.outputs.tag }}

      # Load Golang cache build from GitHub
      - name: Load ${{ matrix.name }} Golang cache build from GitHub
        uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
        id: cache
        with:
          path: /tmp/.cache/${{ matrix.name }}
          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}-${{ matrix.name }}-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}-${{ matrix.name }}-
            ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}-
            ${{ runner.os }}-go-

      - name: Create ${{ matrix.name }} cache directory
        if: ${{ steps.cache.outputs.cache-hit != 'true' }}
        shell: bash
        run: |
          mkdir -p /tmp/.cache/${{ matrix.name }}

      # Import GitHub's cache build to docker cache
      - name: Copy ${{ matrix.name }} Golang cache to docker cache
        uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0
        with:
          provenance: false
          context: /tmp/.cache/${{ matrix.name }}
          file: ./images/cache/Dockerfile
          push: false
          platforms: linux/amd64
          target: import-cache

      - name: Install Cosign
        uses: sigstore/cosign-installer@e1523de7571e31dbe865fd2e80c5c7c23ae71eb4 # v3.4.0

      - name: Install Bom
        shell: bash
        env:
          # renovate: datasource=github-releases depName=kubernetes-sigs/bom
          BOM_VERSION: v0.6.0
        run: |
          curl -L https://github.com/kubernetes-sigs/bom/releases/download/${{ env.BOM_VERSION }}/bom-amd64-linux -o bom
          sudo mv ./bom /usr/local/bin/bom
          sudo chmod +x /usr/local/bin/bom

      # main branch pushes
      - name: CI Build ${{ matrix.name }}
        if: ${{ github.event_name != 'pull_request_target' && !startsWith(github.ref_name, 'ft/') }}
        uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0
        id: docker_build_ci
        with:
          provenance: false
          context: .
          file: ${{ matrix.dockerfile }}
          # Only push when the event name was a GitHub push, this is to avoid
          # re-pushing the image tags when we only want to re-create the Golang
          # docker cache after the workflow "Image CI Cache Cleaner" was terminated.
          push: ${{ github.event_name == 'push' }}
          platforms: linux/amd64,linux/arm64
          tags: |
            quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.floating_tag }}
            quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.tag }}
          target: release
          build-args: |
            OPERATOR_VARIANT=${{ matrix.name }}

      - name: CI race detection Build ${{ matrix.name }}
        if: ${{ github.event_name != 'pull_request_target' && !startsWith(github.ref_name, 'ft/') }}
        uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0
        id: docker_build_ci_detect_race_condition
        with:
          provenance: false
          context: .
          file: ${{ matrix.dockerfile }}
          # Only push when the event name was a GitHub push, this is to avoid
          # re-pushing the image tags when we only want to re-create the Golang
          # docker cache after the workflow "Image CI Cache Cleaner" was terminated.
          push: ${{ github.event_name == 'push' }}
          platforms: linux/amd64
          tags: |
            quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.floating_tag }}-race
            quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.tag }}-race
          target: release
          build-args: |
            BASE_IMAGE=quay.io/cilium/cilium-runtime:272c2080c5c3fc32c2a6ca6b5727daeb12836164@sha256:408484a9f3aaafc41f875254d52af1354822c2d0a694799e90372e0765b27d99
            LOCKDEBUG=1
            RACE=1
            OPERATOR_VARIANT=${{ matrix.name }}

      - name: CI Unstripped Binaries Build ${{ matrix.name }}
        if: ${{ github.event_name != 'pull_request_target' && !startsWith(github.ref_name, 'ft/') }}
        uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0
        id: docker_build_ci_unstripped
        with:
          provenance: false
          context: .
          file: ${{ matrix.dockerfile }}
          # Only push when the event name was a GitHub push, this is to avoid
          # re-pushing the image tags when we only want to re-create the Golang
          # docker cache after the workflow "Image CI Cache Cleaner" was terminated.
          push: ${{ github.event_name == 'push' }}
          platforms: linux/amd64
          tags: |
            quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.floating_tag }}-unstripped
            quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.tag }}-unstripped
          target: release
          build-args: |
            NOSTRIP=1
            OPERATOR_VARIANT=${{ matrix.name }}

      - name: Sign Container Images
        # Only sign when the event name was a GitHub push and not workflow_run (re-building cache).
        # In this case the image wasn't pushed, therefore it's not necessary to execute this step too.
        # It would even fail because `steps.docker_build_ci*.outputs.digest` isn't set in case
        # neither push nor load are set in the docker/build-push-action action.
        if: ${{ github.event_name == 'push' && !startsWith(github.ref_name, 'ft/') }}
        run: |
          cosign sign -y quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci@${{ steps.docker_build_ci.outputs.digest }}
          cosign sign -y quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci@${{ steps.docker_build_ci_detect_race_condition.outputs.digest }}
          cosign sign -y quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci@${{ steps.docker_build_ci_unstripped.outputs.digest }}

      - name: Generate SBOM
        # Only sign when the event name was a GitHub push and not workflow_run (re-building cache).
        # In this case the image wasn't pushed, therefore it's not necessary to execute this step too.
        # It would even fail because `steps.docker_build_ci*.outputs.digest` isn't set in case
        # neither push nor load are set in the docker/build-push-action action.
        if: ${{ github.event_name == 'push' && !startsWith(github.ref_name, 'ft/') }}
        shell: bash
        # To-Do: generate SBOM from source after https://github.com/kubernetes-sigs/bom/issues/202 is fixed
        # To-Do: format SBOM output to json after cosign v2.0 is released with https://github.com/sigstore/cosign/pull/2479
        run: |
          bom generate -o sbom_ci_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx \
          --image=quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.tag }}
          bom generate -o sbom_ci_race_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx \
          --image=quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.tag }}-race
          bom generate -o sbom_ci_unstripped_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx \
          --image=quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.tag }}-unstripped

      - name: Attach SBOM to Container Images
        # Only sign when the event name was a GitHub push and not workflow_run (re-building cache).
        # In this case the image wasn't pushed, therefore it's not necessary to execute this step too.
        # It would even fail because `steps.docker_build_ci*.outputs.digest` isn't set in case
        # neither push nor load are set in the docker/build-push-action action.
        if: ${{ github.event_name == 'push' && !startsWith(github.ref_name, 'ft/') }}
        run: |
          cosign attach sbom --sbom sbom_ci_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci@${{ steps.docker_build_ci.outputs.digest }}
          cosign attach sbom --sbom sbom_ci_race_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci@${{ steps.docker_build_ci_detect_race_condition.outputs.digest }}
          cosign attach sbom --sbom sbom_ci_unstripped_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci@${{ steps.docker_build_ci_unstripped.outputs.digest }}

      - name: Sign SBOM Images
        # Only sign when the event name was a GitHub push and not workflow_run (re-building cache).
        # In this case the image wasn't pushed, therefore it's not necessary to execute this step too.
        # It would even fail because `steps.docker_build_ci*.outputs.digest` isn't set in case
        # neither push nor load are set in the docker/build-push-action action.
        if: ${{ github.event_name == 'push' && !startsWith(github.ref_name, 'ft/') }}
        run: |
          docker_build_ci_digest="${{ steps.docker_build_ci.outputs.digest }}"
          image_name="quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${docker_build_ci_digest/:/-}.sbom"
          docker_build_ci_sbom_digest="sha256:$(docker buildx imagetools inspect --raw ${image_name} | sha256sum | head -c 64)"
          cosign sign -y "quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci@${docker_build_ci_sbom_digest}"

          docker_build_ci_detect_race_condition_digest="${{ steps.docker_build_ci_detect_race_condition.outputs.digest }}"
          image_name="quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${docker_build_ci_detect_race_condition_digest/:/-}.sbom"
          docker_build_ci_detect_race_condition_sbom_digest="sha256:$(docker buildx imagetools inspect --raw ${image_name} | sha256sum | head -c 64)"
          cosign sign -y "quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci@${docker_build_ci_detect_race_condition_sbom_digest}"

          docker_build_ci_unstripped_digest="${{ steps.docker_build_ci_unstripped.outputs.digest }}"
          image_name="quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${docker_build_ci_unstripped_digest/:/-}.sbom"
          docker_build_ci_unstripped_sbom_digest="sha256:$(docker buildx imagetools inspect --raw ${image_name} | sha256sum | head -c 64)"
          cosign sign -y "quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci@${docker_build_ci_unstripped_sbom_digest}"

      - name: CI Image Releases digests
        # Only sign when the event name was a GitHub push and not workflow_run (re-building cache).
        # In this case the image wasn't pushed, therefore it's not necessary to execute this step too.
        # It would even fail because `steps.docker_build_ci*.outputs.digest` isn't set in case
        # neither push nor load are set in the docker/build-push-action action.
        if: ${{ github.event_name == 'push' && !startsWith(github.ref_name, 'ft/') }}
        shell: bash
        run: |
          mkdir -p image-digest/
          echo "quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.floating_tag }}@${{ steps.docker_build_ci.outputs.digest }}" > image-digest/${{ matrix.name }}.txt
          echo "quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.floating_tag }}-race@${{ steps.docker_build_ci_detect_race_condition.outputs.digest }}" >> image-digest/${{ matrix.name }}.txt
          echo "quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.floating_tag }}-unstripped@${{ steps.docker_build_ci_unstripped.outputs.digest }}" >> image-digest/${{ matrix.name }}.txt
          echo "quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.tag }}@${{ steps.docker_build_ci.outputs.digest }}" >> image-digest/${{ matrix.name }}.txt
          echo "quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.tag }}-race@${{ steps.docker_build_ci_detect_race_condition.outputs.digest }}" >> image-digest/${{ matrix.name }}.txt
          echo "quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.tag }}-unstripped@${{ steps.docker_build_ci_unstripped.outputs.digest }}" >> image-digest/${{ matrix.name }}.txt

      # PR or feature branch updates
      - name: CI Build ${{ matrix.name }}
        if: ${{ github.event_name == 'pull_request_target' || (github.event_name == 'push' && startsWith(github.ref_name, 'ft/')) }}
        uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0
        id: docker_build_ci_pr
        with:
          provenance: false
          context: .
          file: ${{ matrix.dockerfile }}
          push: true
          platforms: linux/amd64,linux/arm64
          tags: |
            quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.tag }}
          target: release
          build-args: |
            OPERATOR_VARIANT=${{ matrix.name }}

      - name: CI race detection Build ${{ matrix.name }}
        if: ${{ github.event_name == 'pull_request_target' || (github.event_name == 'push' && startsWith(github.ref_name, 'ft/')) }}
        uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0
        id: docker_build_ci_pr_detect_race_condition
        with:
          provenance: false
          context: .
          file: ${{ matrix.dockerfile }}
          push: true
          platforms: linux/amd64
          tags: |
            quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.tag }}-race
          target: release
          build-args: |
            BASE_IMAGE=quay.io/cilium/cilium-runtime:272c2080c5c3fc32c2a6ca6b5727daeb12836164@sha256:408484a9f3aaafc41f875254d52af1354822c2d0a694799e90372e0765b27d99
            LOCKDEBUG=1
            RACE=1
            OPERATOR_VARIANT=${{ matrix.name }}

      - name: CI Unstripped Binaries Build ${{ matrix.name }}
        if: ${{ github.event_name == 'pull_request_target' || (github.event_name == 'push' && startsWith(github.ref_name, 'ft/')) }}
        uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0
        id: docker_build_ci_pr_unstripped
        with:
          provenance: false
          context: .
          file: ${{ matrix.dockerfile }}
          push: true
          platforms: linux/amd64
          tags: |
            quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.tag }}-unstripped
          target: release
          build-args: |
            NOSTRIP=1
            OPERATOR_VARIANT=${{ matrix.name }}

      - name: Sign Container Images
        if: ${{ github.event_name == 'pull_request_target' || (github.event_name == 'push' && startsWith(github.ref_name, 'ft/')) }}
        run: |
          cosign sign -y quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci@${{ steps.docker_build_ci_pr.outputs.digest }}
          cosign sign -y quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci@${{ steps.docker_build_ci_pr_detect_race_condition.outputs.digest }}
          cosign sign -y quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci@${{ steps.docker_build_ci_pr_unstripped.outputs.digest }}

      - name: Generate SBOM
        if: ${{ github.event_name == 'pull_request_target' || (github.event_name == 'push' && startsWith(github.ref_name, 'ft/')) }}
        shell: bash
        # To-Do: generate SBOM from source after https://github.com/kubernetes-sigs/bom/issues/202 is fixed
        # To-Do: format SBOM output to json after cosign v2.0 is released with https://github.com/sigstore/cosign/pull/2479
        run: |
          bom generate -o sbom_ci_pr_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx \
          --image=quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.tag }}
          bom generate -o sbom_ci_pr_race_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx \
          --image=quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.tag }}-race
          bom generate -o sbom_ci_pr_unstripped_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx \
          --image=quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.tag }}-unstripped

      - name: Attach SBOM to Container Images
        if: ${{ github.event_name == 'pull_request_target' || (github.event_name == 'push' && startsWith(github.ref_name, 'ft/')) }}
        run: |
          cosign attach sbom --sbom sbom_ci_pr_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci@${{ steps.docker_build_ci_pr.outputs.digest }}
          cosign attach sbom --sbom sbom_ci_pr_race_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci@${{ steps.docker_build_ci_pr_detect_race_condition.outputs.digest }}
          cosign attach sbom --sbom sbom_ci_pr_unstripped_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci@${{ steps.docker_build_ci_pr_unstripped.outputs.digest }}

      - name: Sign SBOM Images
        if: ${{ github.event_name == 'pull_request_target' || (github.event_name == 'push' && startsWith(github.ref_name, 'ft/')) }}
        run: |
          docker_build_ci_pr_digest="${{ steps.docker_build_ci_pr.outputs.digest }}"
          image_name="quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${docker_build_ci_pr_digest/:/-}.sbom"
          docker_build_ci_pr_sbom_digest="sha256:$(docker buildx imagetools inspect --raw ${image_name} | sha256sum | head -c 64)"
          cosign sign -y "quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci@${docker_build_ci_pr_sbom_digest}"

          docker_build_ci_pr_detect_race_condition_digest="${{ steps.docker_build_ci_pr_detect_race_condition.outputs.digest }}"
          image_name="quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${docker_build_ci_pr_detect_race_condition_digest/:/-}.sbom"
          docker_build_ci_pr_detect_race_condition_sbom_digest="sha256:$(docker buildx imagetools inspect --raw ${image_name} | sha256sum | head -c 64)"
          cosign sign -y "quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci@${docker_build_ci_pr_detect_race_condition_sbom_digest}"

          docker_build_ci_pr_unstripped_digest="${{ steps.docker_build_ci_pr_unstripped.outputs.digest }}"
          image_name="quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${docker_build_ci_pr_unstripped_digest/:/-}.sbom"
          docker_build_ci_pr_unstripped_sbom_digest="sha256:$(docker buildx imagetools inspect --raw ${image_name} | sha256sum | head -c 64)"
          cosign sign -y "quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci@${docker_build_ci_pr_unstripped_sbom_digest}"

      - name: CI Image Releases digests
        if: ${{ github.event_name == 'pull_request_target' || (github.event_name == 'push' && startsWith(github.ref_name, 'ft/')) }}
        shell: bash
        run: |
          mkdir -p image-digest/
          echo "quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.tag }}@${{ steps.docker_build_ci_pr.outputs.digest }}" > image-digest/${{ matrix.name }}.txt
          echo "quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.tag }}-race@${{ steps.docker_build_ci_pr_detect_race_condition.outputs.digest }}" >> image-digest/${{ matrix.name }}.txt
          echo "quay.io/${{ env.QUAY_ORGANIZATION_DEV }}/${{ matrix.name }}-ci:${{ steps.tag.outputs.tag }}-unstripped@${{ steps.docker_build_ci_pr_unstripped.outputs.digest }}" >> image-digest/${{ matrix.name }}.txt

      # Upload artifact digests
      - name: Upload artifact digests
        uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
        with:
          name: image-digest ${{ matrix.name }}
          path: image-digest
          retention-days: 1

      # Store docker's golang's cache build locally only on the main branch
      - name: Store ${{ matrix.name }} Golang cache build locally
        if: ${{ github.event_name != 'pull_request_target' && steps.cache.outputs.cache-hit != 'true' && github.ref_name == github.event.repository.default_branch }}
        uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0
        with:
          provenance: false
          context: .
          file: ./images/cache/Dockerfile
          push: false
          outputs: type=local,dest=/tmp/docker-cache-${{ matrix.name }}
          platforms: linux/amd64
          target: export-cache

      # Store docker's golang's cache build locally only on the main branch
      - name: Store ${{ matrix.name }} Golang cache in GitHub cache path
        if: ${{ github.event_name != 'pull_request_target' && steps.cache.outputs.cache-hit != 'true' && github.ref_name == github.event.repository.default_branch }}
        shell: bash
        run: |
          mkdir -p /tmp/.cache/${{ matrix.name }}/
          if [ -f /tmp/docker-cache-${{ matrix.name }}/tmp/go-build-cache.tar.gz ]; then
            cp /tmp/docker-cache-${{ matrix.name }}/tmp/go-build-cache.tar.gz /tmp/.cache/${{ matrix.name }}/
          fi
          if [ -f /tmp/docker-cache-${{ matrix.name }}/tmp/go-pkg-cache.tar.gz ]; then
            cp /tmp/docker-cache-${{ matrix.name }}/tmp/go-pkg-cache.tar.gz /tmp/.cache/${{ matrix.name }}/
          fi

  image-digests:
    if: ${{ always() }}
    name: Display Digests
    runs-on: ubuntu-22.04
    needs: build-and-push-prs
    steps:
      - name: Downloading Image Digests
        shell: bash
        run: |
          mkdir -p image-digest/

      - name: Download digests of all images built
        uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2
        with:
          path: image-digest/

      - name: Image Digests Output
        shell: bash
        run: |
          cd image-digest/
          find -type f | sort | xargs -d '\n' cat
